package org.raymond.iworks.study.basic.thread.countdownlatch;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;

@Slf4j
public class Demo1 {
    public static void main(String[] args) throws InterruptedException {
      test1();
    }

    public static void test1() throws InterruptedException {
        CountDownLatch longThead = new CountDownLatch(3);
        Thread t1 = new Thread(()->{
            try {
                log.info("开始工作1");
                Thread.sleep(1000*1);
                log.info("结束工作1");
                longThead.countDown();
                log.info("结束工作1之后");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        Thread t2 = new Thread(()->{
            try {
                log.info("开始工作2");
                Thread.sleep(2000*1);
                log.info("结束工作2");
                longThead.countDown();
                log.info("结束工作2之后");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        Thread t3 = new Thread(()->{
            try {
                log.info("开始工作3");
                Thread.sleep(3000*1);
                log.info("结束工作3");
                longThead.countDown();
                log.info("结束工作3之后");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        t1.start();
        t2.start();
        t3.start();

        log.info("开始准备工作");
        Thread.sleep(1000*1);
        log.info("准备工作完成");
        longThead.await();
        log.info("所有工作都结束,可以汇总报告了");
    }

    public static void test2() throws InterruptedException{
        int n = 100;
        // 启动信号
        CountDownLatch start = new CountDownLatch(1);
        // 完成信号
        CountDownLatch done = new CountDownLatch(n);
        for(int i=0; i<n; i++){
            new Thread(new Work(start, done)).start();
        }
        log.info("先完成准备工作");
        Thread.sleep(1000*5);
        log.info("触发启动信号,让所有线程开始工作");
        start.countDown();
        log.info("触发等待完成信号,等待所有线程完成");
        done.await();
        log.info("所有线程任务已完成");
    }

    // 靠计数来判断任务是否都结束,与任务本身是解藕的,一个线程里不要countDown多次
    public static void test3() throws InterruptedException {
        CountDownLatch longThead = new CountDownLatch(2);
        Thread t1 = new Thread(()->{
            try {
                log.info("开始工作1");
                Thread.sleep(1*1);
                log.info("结束工作1 1次");
                longThead.countDown();
                log.info("结束工作1 2次");
                longThead.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        t1.start();
        log.info("await之前");
        longThead.await();
        log.info("await之后");
    }

    static class Work implements Runnable{
        private final CountDownLatch start;
        private final CountDownLatch done;

        public Work(CountDownLatch start, CountDownLatch done){
            this.start = start;
            this.done = done;
        }
        @Override
        public void run() {
            try{
                start.await();
                doWork();
                done.countDown();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }

        private void doWork(){
            System.out.println(Thread.currentThread().getName());
        }
    }
}
